热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

时会|终点_SpringRestTemplate专题

篇首语:本文由编程笔记#小编为大家整理,主要介绍了SpringRestTemplate专题相关的知识,希望对你有一定的参考价值。

篇首语:本文由编程笔记#小编为大家整理,主要介绍了Spring RestTemplate 专题相关的知识,希望对你有一定的参考价值。




相同的参数(接口的入参json打印在日志了)在PostMan中返回预期的数据,但使用RestTemplate时去提示信息错误(参数中汉字)。
这种情况,搞得怀疑对RestTemplate的理解了
使用RestTemplate的代码如下:

JSONObject reqVO = new JSONObject(12);
reqVO.put("token", smsConfig.getToken());
reqVO.put("phones", new String[]mobile.toString());//一个或多个号码数组,一次不能超过10
reqVO.put("content", "content,包含汉字");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
String jsOnPost= reqVO.toString();
HttpEntity entity = new HttpEntity<>(jsonPost, headers);
ResponseEntity respOnseEntity= restTemplate.postForEntity(smsConfig.getUrl(), entity, String.class);
String body = responseEntity.getBody();

 

解决办法,通过wireshark抓包:
使用Postman发送时情况:

Spring

使用上面的代码调接口时的http数据情况:

Spring

 

/**
* A String equivalent of @link MediaType#APPLICATION_JSON.
* @see #APPLICATION_JSON_UTF8_VALUE
*/
public final static String APPLICATION_JSON_VALUE = "application/json";
/**
* Public constant media type for @code application/json;charset=UTF-8.
*/
public final static MediaType APPLICATION_JSON_UTF8;

只更改上面中设置Content-type的这行代码,更改后的:

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);

 

上面 wireshark的过滤器:

ip.dst==目标接口的ip地址 and tcp.port==80 and http.request.method="POST"

 Tips:

wireshark是非常流行的网络封包分析软件,功能十分强大。可以截取各种网络封包,显示网络封包的详细信息。使用wireshark的人必须了解网络协议,否则就看不懂wireshark了。

为了安全考虑,wireshark只能查看封包,而不能修改封包的内容,或者发送封包。

wireshark能获取HTTP,也能获取HTTPS,但是不能解密HTTPS,所以wireshark看不懂HTTPS中的内容,总结,如果是处理HTTP,HTTPS 还是用Fiddler, 其他协议比如TCP,UDP 就用wireshark.

Spring

过滤表达式的规则

表达式规则

 1. 协议过滤

比如TCP,只显示TCP协议。

2. IP 过滤

比如 ip.src ==192.168.1.102 显示源地址为192.168.1.102,

ip.dst==192.168.1.102, 目标地址为192.168.1.102

3. 端口过滤

tcp.port ==80,  端口为80的

tcp.srcport == 80,  只显示TCP协议的愿端口为80的。

4. Http模式过滤

http.request.method=="GET",   只显示HTTP GET方法的。

5. 逻辑运算符为 AND/ OR

常用的过滤表达式

过滤表达式

用途

http

只查看HTTP协议的记录

ip.src ==192.168.1.102 or ip.dst==192.168.1.102

 源地址或者目标地址是192.168.1.102

 

 

 

 

 

 

 

 

封包列表(Packet List Pane)

封包列表的面板中显示,编号,时间戳,源地址,目标地址,协议,长度,以及封包信息。 你可以看到不同的协议用了不同的颜色显示。


 

restTemplate使用及中文乱码问题

 

public T restTemplate(String url, Map params, Class var, HttpMethod method)
RestTemplate restTemplate = new RestTemplate();
FormHttpMessageConverter fc = new FormHttpMessageConverter();
StringHttpMessageConverter s = new StringHttpMessageConverter(StandardCharsets.UTF_8);
List> partCOnverters= new ArrayList>();
partConverters.add(s);
partConverters.add(new ResourceHttpMessageConverter());
fc.setPartConverters(partConverters);
restTemplate.getMessageConverters().addAll(Arrays.asList(fc, new MappingJackson2HttpMessageConverter()));
MultiValueMap map = new LinkedMultiValueMap<>();
map.setAll(params);
switch (method)
case POST:
return restTemplate.postForObject(url, map, var);
case GET:
String getParams = "?" + map.keySet().stream().map(k -> String.format("%s=%s", k, k)).collect(Collectors.joining("&"));
return restTemplate.getForObject(url + getParams, var, params);
default:
return restTemplate.postForObject(url, map, var);

所要注意的是get请求要求我们对URL中参数用占位符封装,user/getUser?userId=userId&fe=
fe,就像这样,所以我在封装get请求时有一个拼接URL的操作。


问题描述

我没有找到任何例子来解决我的问题,所以我想请你帮忙。我不能简单地使用JSON中的RestTemplate对象发送POST请求

每次我得到org.springframework.web.client.HttpClientErrorException:415不支持的媒体类型

我以这种方式使用RestTemplate:

...
restTemplate = new RestTemplate();
List> list = new ArrayList>();
list.add(new MappingJacksonHttpMessageConverter());
restTemplate.setMessageConverters(list);
...
Payment payment= new Payment("Aa4bhs");
Payment res = restTemplate.postForObject("http://localhost:8080/aurest/rest/payment", payment, Payment.class);

我的错是什么

 

最佳解决方案

这种技术对我有用:

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity entity = new HttpEntity(requestJson,headers);
restTemplate.put(uRL, entity);

我希望这有帮助

KD

 

次佳解决方案

我一直在使用具有JSONObjects的rest模板,如下所示:

// create request body
JSONObject request = new JSONObject();
request.put("username", name);
request.put("password", password);
// set headers
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity entity = new HttpEntity(request.toString(), headers);
// send request and parse result
ResponseEntity loginRespOnse= restTemplate
.exchange(urlString, HttpMethod.POST, entity, String.class);
if (loginResponse.getStatusCode() == HttpStatus.OK)
JSONObject userJson = new JSONObject(loginResponse.getBody());
else if (loginResponse.getStatusCode() == HttpStatus.UNAUTHORIZED)
// nono... bad credentials

 

第三种解决方案

尝试调试REST端点时,我遇到这个问题。这是使用Spring的RestTemplate类来创建我使用的POST请求的一个基本示例。我花了很长时间把不同地方的代码整理成一个工作版本。

RestTemplate restTemplate = new RestTemplate();
String url = "endpoint url";
String requestJson = "\\"queriedQuestion\\":\\"Is there pain in your hand?\\"";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity entity = new HttpEntity(requestJson,headers);
String answer = restTemplate.postForObject(url, entity, String.class);
System.out.println(answer);

特定的JSON解析器我的休息终点是使用围绕字段名称的双引号,这就是为什么我在我的requestJson String中转义了双引号。

 

第四种方案

根据指定的​​here​​​我想你需要添加一个​​messageConverter​​​为​​MappingJacksonHttpMessageConverter​

 

第五种方案

“415不支持的媒体类型”错误告诉您服务器将不接受您的POST请求。您的请求绝对不错,这是mis-configured的服务器。

​MappingJacksonHttpMessageConverter​​​会自动将请求content-type标头设置为​​application/json​​,我的猜测是您的服务器拒绝了。你没有告诉我们任何关于你的服务器设置,所以我不能真的建议你。

 

第六种方案

如果您使用的是Spring 3.0,则可以避免使用org.springframework.web.client.HttpClientErrorException:415不支持的介质类型异常的简单方法是将jackson jar文件包含在类路径中,并使用​​mvc:annotation-driven​​​ config元素。 ​​As specified here​​。

我正在拉我的头发,试图找出为什么​​mvc-ajax​​​应用程序工作没有任何特殊的配置为​​MappingJacksonHttpMessageConverter​​。如果你仔细阅读我所链接的文章:

Underneath the covers, Spring MVC delegates to a HttpMessageConverter to perform the serialization. In this case, Spring MVC invokes a MappingJacksonHttpMessageConverter built on the Jackson JSON processor. This implementation is enabled automatically when you use the mvc:annotation-driven configuration element with Jackson present in your classpath.

参考文献

  • ​​POST request via RestTemplate in JSON​​

 

注:本文内容整合自google/baidu/bing辅助翻译的英文资料结果。如果您对结果不满意



RestTemplate

这篇文章打算介绍一下Spring的​​RestTemplate​​​。我这边以前设计到http交互的,之前一直采用的是​​Apache HttpComponents​​ 。后来发现Spring框架中已经为我们封装好了这个框架。因此我们就不需要直接使用下面这种稍微底层一点的方式来实现我们的功能:

String uri = "http://example.com/hotels/1/bookings";
PostMethod post = new PostMethod(uri);
String request = // create booking request content
post.setRequestEntity(new StringRequestEntity(request));
httpClient.executeMethod(post);
if (HttpStatus.SC_CREATED == post.getStatusCode())
Header location = post.getRequestHeader("Location");
if (location != null)
System.out.println("Created new booking at :" + location.getValue());

Spring的RestTemplate提供了一些更高级别的方法来满足我们的功能,比如对HTTP Method的支持:

Spring

虽然Spring的RestTemplate提供了对这么多HTTP method的支持,但是从个人工作角度来说,常用的也就get和post这两种方式,有兴趣的朋友可以自己翻看一下源码。

RestTemplate的使用

RestTemplate有两个构造方法,分别是:

public RestTemplate()
/**
...初始化过程
*/

public RestTemplate(ClientHttpRequestFactory requestFactory)
this();
setRequestFactory(requestFactory);

其中,第二个构造方法中可以传入ClientHttpRequestFactory参数,第一个进行默认初始化,因为我们经常需要对请求超时进行设置并能够对超时进行后续处理,而第一个构造方法,我们无法控制超时时间,第二个构造中的ClientHttpRequestFactory接口的实现类中存在timeout属性,因此选用第二个构造方法。
在spring配置文件中进行如下配置:











当然也可以直接使用:

SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setConnectTimeout(1000);
requestFactory.setReadTimeout(1000);
RestTemplate restTemplate = new RestTemplate(requestFactory);

注意:ClientHttpRequestFactory 接口有4个实现类,分别是:

  • AbstractClientHttpRequestFactoryWrapper 用来装配其他request factory的抽象类。
  • CommonsClientHttpRequestFactory 允许用户配置带有认证和http连接池的httpclient,已废弃,推荐用HttpComponentsClientHttpRequestFactory。
  • HttpComponentsClientHttpRequestFactory 同2.
  • SimpleClientHttpRequestFactory 接口的一个简单实现,可配置proxy,connectTimeout,readTimeout等参数。

GET

Spring的RestTemplate提供了许多的支持,这里仅仅列出常用的接口:

public T getForObject(String url, Class responseType, Object... urlVariables) throws RestClientException
public T getForObject(String url, Class responseType, Map urlVariables) throws RestClientException
public T getForObject(URI url, Class responseType) throws RestClientException

对于GET请求来说,我一般常用的几种形式如下:

String result = restTemplate.getForObject("http://example.com/hotels/hotel/bookings/booking", String.class,"42", "21");

或者下面这张形式:

Map vars = Collections.singletonMap("hotel", "42");
String result = restTemplate.getForObject("http://example.com/hotels/hotel/rooms/hotel", String.class, vars);

以及:
​​​java String message = restTemplate.getForObject("http://localhost:8080/yongbarservice/appstore/appgoods/restTemplate?name=zhaoshijie&id=80", String.class );​

他这种做法参考了​​uri-templates​​​(​​https://code.google.com/p/uri-templates/)这个项目。​​

POST

Spring的RestTemplate对post的常用接口:

public T postForObject(String url, Object request, Class responseType, Object... uriVariables)
throws RestClientException
public T postForObject(String url, Object request, Class responseType, Map uriVariables)
throws RestClientException
public T postForObject(URI url, Object request, Class responseType) throws RestClientException

我一般常用的方法为:

MultiValueMap bodyMap = new LinkedMultiValueMap();
bodyMap.setAll(urlVariables);
ResponseClass respOnseClass= restTemplate.postForObject(CAR_CES_URL, bodyMap, ResponseClass.class);

以及:

HttpHeaders headers = new HttpHeaders();
headers.add("X-Auth-Token", "e348bc22-5efa-4299-9142-529f07a18ac9");
MultiValueMap postParameters = new LinkedMultiValueMap();
postParameters.add("owner", "11");
postParameters.add("subdomain", "aoa");
postParameters.add("comment", "");
HttpEntity> requestEntity = new HttpEntity>(postParameters, headers);
ParseResultVo exchange = null;
try
exchange = restTemplate.postForObject("http://l-dnsutil1.ops.beta.cn6.qunar.com:10085/v1/cnames/tts.piao", requestEntity, ParseResultVo.class);
logger.info(exchange.toString());
catch (RestClientException e)
logger.info("。。。。");

以及:

DomainParam domainParam = new DomainParam();
domainParam.setCustomerId(1);
//...
logger.info("....");
restTemplate.getMessageConverters().add(new MappingJacksonHttpMessageConverter());
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
String respOnseResult= restTemplate.postForObject(url, domainParam, String.class);

其他

​PUT​​方式:

restTemplate.put("http://localhost:8080/yongbarservice/appstore/appgoods/restTemplate?name=zhaoshijie&id=80" ,null);

​DELETE​​方式

//delete方法(注意:delete方法没有返回值,说明,id=0这个参数在服务器端可以不定义该参数,直接使用request获取)
// restTemplate.delete("http://localhost:8080/yongbarservice/appstore/appgoods/deleteranking?id=0");

参考资料:

  • ​​http://docs.spring.io/spring/docs/4.0.1.BUILD-SNAPSHOT/spring-framework-reference/htmlsingle/#rest-resttemplate​​
  • ​​http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html​​


1. Overview

In this tutorial, we’re going to illustrate the broad range of operations where the Spring REST Client – RestTemplate – can be used, and used well.

For the API side of all examples, we’ll be running the RESTful service from ​​here​​.

Further reading:

Basic Authentication with the RestTemplate

How to do Basic Authentication with the Spring RestTemplate.

​​Read more​​ →

RestTemplate with Digest Authentication

How to set up Digest Authentication for the Spring RestTemplate using HttpClient 4.

​​Read more​​ →

HttpClient 4 Tutorial

Comprehensive Guide to the Apache HttpClient - start with basic usage and make your way though the advanced scenarios.

​​Read more​​ →

2. Use GET to Retrieve Resources

2.1. Get Plain JSON

Let’s start simple and talk about GET requests – with a quick example using the getForEntity() API:

​​RestTemplate restTemplate = ​​​​new​​​ ​​RestTemplate();​​
​​String fooResourceUrl​​
​​= ​​​​"http://localhost:8080/spring-rest/foos"​​​​;​​
​​ResponseEntity response​​
​​= restTemplate.getForEntity(fooResourceUrl + ​​​​"/1"​​​​, String.​​​​class​​​​);​​
​​assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));​​

Notice that we have full access to the HTTP response – so we can do things like checking the status code to make sure the operation was actually successful, or work with the actual body of the response:

​​ObjectMapper mapper = ​​​​new​​​ ​​ObjectMapper();​​
​​JsonNode root = mapper.readTree(response.getBody());​​
​​JsonNode name = root.path(​​​​"name"​​​​);​​
​​assertThat(name.asText(), notNullValue());​​

We’re working with the response body as a standard String here – and using Jackson (and the JSON node structure that Jackson provides) to verify some details.

2.1. Retrieving POJO Instead of JSON

We can also map the response directly to a Resource DTO – for example:

​​public​​​ ​​class​​​ ​​Foo ​​​​implements​​​ ​​Serializable ​​
​​private​​​ ​​long​​​ ​​id;​​

​​private​​​ ​​String name;​​
​​// standard getters and setters​​
​​​​

Now – we can simply use the getForObject API in the template:

​​Foo foo = restTemplate​​
​​.getForObject(fooResourceUrl + ​​​​"/1"​​​​, Foo.​​​​class​​​​);​​
​​assertThat(foo.getName(), notNullValue());​​
​​assertThat(foo.getId(), is(1L));​​

3. Use HEAD to Retrieve Headers

Let’s now have a quick look at using HEAD before moving on to the more common methods – we’re going to be using the headForHeaders() API here:

​​HttpHeaders httpHeaders = restTemplate​​
​​.headForHeaders(fooResourceUrl);​​
​​assertTrue(httpHeaders.getContentType()​​
​​.includes(MediaType.APPLICATION_JSON));​​

4. Use POST to Create a Resource

In order to create a new Resource in the API – we can make good use of the postForLocation()postForObject() or postForEntity() APIs.

The first returns the URI of the newly created Resource while the second returns the Resource itself.

4.1. The postForObject API

​​ClientHttpRequestFactory requestFactory = getClientHttpRequestFactory();​​
​​RestTemplate restTemplate = ​​​​new​​​ ​​RestTemplate(requestFactory);​​

​​HttpEntity request = ​​​​new​​​ ​​HttpEntity<>(​​​​new​​​ ​​Foo(​​​​"bar"​​​​));​​
​​Foo foo = restTemplate.postForObject(fooResourceUrl, request, Foo.​​​​class​​​​);​​
​​assertThat(foo, notNullValue());​​
​​assertThat(foo.getName(), is(​​​​"bar"​​​​));​​




4.2. The postForLocation API

Similarly, let’s have a look at the operation that – instead of returning the full Resource, just returns the Location of that newly created Resource:

​​HttpEntity request = ​​​​new​​​ ​​HttpEntity<>(​​​​new​​​ ​​Foo(​​​​"bar"​​​​));​​
​​URI location = restTemplate​​
​​.postForLocation(fooResourceUrl, request);​​
​​assertThat(location, notNullValue());​​

4.3. The exchange API

Finally, let’s have a look at how to do a POST with the more generic exchange API:

​​RestTemplate restTemplate = ​​​​new​​​ ​​RestTemplate();​​
​​HttpEntity request = ​​​​new​​​ ​​HttpEntity<>(​​​​new​​​ ​​Foo(​​​​"bar"​​​​));​​
​​ResponseEntity respOnse= restTemplate​​
​​.exchange(fooResourceUrl, HttpMethod.POST, request, Foo.​​​​class​​​​);​​

​​assertThat(response.getStatusCode(), is(HttpStatus.CREATED));​​

​​Foo foo = response.getBody();​​

​​assertThat(foo, notNullValue());​​
​​assertThat(foo.getName(), is(​​​​"bar"​​​​));​​

5. Use OPTIONS to get Allowed Operations

Next, we’re going to have a quick look at using an OPTIONS request and exploring the allowed operations on a specific URI using this kind of request; the API is optionsForAllow:

​​Set optiOnsForAllow= restTemplate.optionsForAllow(fooResourceUrl);​​
​​HttpMethod[] supportedMethods​​
​​= HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE;​​
​​assertTrue(optionsForAllow.containsAll(Arrays.asList(supportedMethods)));​​

6. Use PUT to Update a Resource

Next, we’ll start looking at PUT – and more specifically the exchange API for this operation, because of the template.put API is pretty straightforward.

6.1. Simple PUT with .exchange

We’ll start with a simple PUT operation against the API – and keep in mind that the operation isn’t returning anybody back to the client:

​​Foo updatedInstance = ​​​​new​​​ ​​Foo(​​​​"newName"​​​​);​​
​​updatedInstance.setId(createResponse.getBody().getId());​​
​​String resourceUrl = ​​
​​fooResourceUrl + ​​​​/​​​ ​​+ createResponse.getBody().getId();​​
​​HttpEntity requestUpdate = ​​​​new​​​ ​​HttpEntity<>(updatedInstance, headers);​​
​​template.exchange(resourceUrl, HttpMethod.PUT, requestUpdate, Void.​​​​class​​​​);​​

6.2. PUT with .exchange and a Request Callback

Next, we’re going to be using a request callback to issue a PUT.

Let’s make sure we prepare the callback – where we can set all the headers we need as well as a request body:

​​RequestCallback requestCallback(​​​​final​​​ ​​Foo updatedInstance) ​​
​​return​​​ ​​clientHttpRequest -> ​​
​​ObjectMapper mapper = ​​​​new​​​ ​​ObjectMapper();​​
​​mapper.writeValue(clientHttpRequest.getBody(), updatedInstance);​​
​​clientHttpRequest.getHeaders().add(​​
​​HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);​​
​​clientHttpRequest.getHeaders().add(​​
​​HttpHeaders.AUTHORIZATION, ​​​​"Basic "​​​ ​​+ getBase64EncodedLogPass());​​
​​;​​
​​​​

Next, we create the Resource with POST request:

​​ResponseEntity respOnse= restTemplate​​
​​.exchange(fooResourceUrl, HttpMethod.POST, request, Foo.​​​​class​​​​);​​
​​assertThat(response.getStatusCode(), is(HttpStatus.CREATED));​​

And then we update the Resource:

​​Foo updatedInstance = ​​​​new​​​ ​​Foo(​​​​"newName"​​​​);​​
​​updatedInstance.setId(response.getBody().getId());​​
​​String resourceUrl =fooResourceUrl + ​​​​/​​​ ​​+ response.getBody().getId();​​
​​restTemplate.execute(​​
​​resourceUrl, ​​
​​HttpMethod.PUT, ​​
​​requestCallback(updatedInstance), ​​
​​clientHttpResponse -> ​​​​null​​​​);​​

7. Use DELETE to Remove a Resource

To remove an existing Resource we’ll make short work of the delete() API:

​​String entityUrl = fooResourceUrl + ​​​​"/"​​​ ​​+ existingResource.getId();​​
​​restTemplate.delete(entityUrl);​​

8. Configure Timeout

We can configure RestTemplate to time out by simply using ClientHttpRequestFactory – as follows:

​​RestTemplate restTemplate = ​​​​new​​​ ​​RestTemplate(getClientHttpRequestFactory());​​

​​private​​​ ​​ClientHttpRequestFactory getClientHttpRequestFactory() ​​
​​int​​​ ​​timeout = ​​​​5000​​​​;​​
​​HttpComponentsClientHttpRequestFactory clientHttpRequestFactory​​
​​= ​​​​new​​​ ​​HttpComponentsClientHttpRequestFactory();​​
​​clientHttpRequestFactory.setConnectTimeout(timeout);​​
​​return​​​ ​​clientHttpRequestFactory;​​
​​​​

And we can use HttpClient for further configuration options – as follows:

​​private​​​ ​​ClientHttpRequestFactory getClientHttpRequestFactory() ​​
​​int​​​ ​​timeout = ​​​​5000​​​​;​​
​​RequestConfig cOnfig= RequestConfig.custom()​​
​​.setConnectTimeout(timeout)​​
​​.setConnectionRequestTimeout(timeout)​​
​​.setSocketTimeout(timeout)​​
​​.build();​​
​​CloseableHttpClient client = HttpClientBuilder​​
​​.create()​​
​​.setDefaultRequestConfig(config)​​
​​.build();​​
​​return​​​ ​​new​​​ ​​HttpComponentsClientHttpRequestFactory(client);​​
​​​​

9. Conclusion

We went over the main HTTP Verbs, using RestTemplate to orchestrate requests using all of these.

If you want to dig into how to do authentication with the template – check out my write-up ​​on Basic Auth with RestTemplate​​.

The implementation of all these examples and code snippets can be found in ​​my GitHub project​​

​​http://www.baeldung.com/rest-template​​

RestTemplate:
设置代理

Configure RestTemplate to Use a Proxy
As described in Section 33.1, “RestTemplate Customization”, you can use a RestTemplateCustomizer with RestTemplateBuilder to build a customized RestTemplate.
This is the recommended approach for creating a RestTemplate configured to use a proxy.

The exact details of the proxy configuration depend on the underlying client request factory that is being used.
The following example configures HttpComponentsClientRequestFactory with an HttpClient that uses a proxy for all hosts except 192.168.0.5:

static class ProxyCustomizer implements RestTemplateCustomizer
@Override
public void customize(RestTemplate restTemplate)
HttpHost proxy = new HttpHost("proxy.example.com");
HttpClient httpClient = HttpClientBuilder.create()
.setRoutePlanner(new DefaultProxyRoutePlanner(proxy)
@Overridepublic HttpHost determineProxy(HttpHost target, HttpRequest request, HttpContext context) throws HttpException if (target.getHostName().equals("192.168.0.5")) return null; return super.determineProxy(target, request, context);
).build();
restTemplate.setRequestFactory(
new HttpComponentsClientHttpRequestFactory(httpClient));

​​https://docs.spring.io/spring-boot/docs/2.0.0.RELEASE/reference/htmlsingle/#howto-reload-thymeleaf-content​​

RestTempate中处理返回值中带有泛型的API:
resttemplate是一个很方便的HTTP客户端,但是当返回的数据类型是泛型时会报错

//一般用法,通过postForObject获取结果
REST_TEMPLATE.postForObject(supplier.getApi(),param,Result.class)
//Result.java
public class Result
private int code;
private List data;
...
//报错
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to xxx

原因:
postForObject无法知道具体的实例化类型,解析为了LinkedHashMap
解决方法,使用exchange方法替代:

Map param = new HashedMap();
param.put("key","value");//传入参数
parameterizedTypeReference =
new ParameterizedTypeReference>();
//XXX为实例化的类型
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity entity = new HttpEntity<>(new Gson().toJson(param),headers);
ResponseEntity> result =
REST_TEMPLATE.exchange(url, HttpMethod.POST, entity, parameterizedTypeReference);

链接:https://www.jianshu.com/p/597066dec24d

 

上传文件:
使用RestTemplate调用文件上传接口时有什么特别的地方呢?实际上只需要注意一点就行了,就是创建文件资源时需要使用org.springframework.core.io.FileSystemResource类,而不能直接使用java.io.File对象。

URI uri = UriComponentsBuilder.fromHttpUrl("https://qyapi.weixin.qq.com/cgi-bin/media/upload")
.queryParam("access_token", cpToken)
.queryParam("type", file.getParaName())
.build().toUri();
MultiValueMap body = new LinkedMultiValueMap<>();
FileSystemResource resource = new FileSystemResource(targetFile);//文件,使用FileSystemResource才能判断出类型
body.add("media", resource);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
HttpEntity> request = new HttpEntity<>(body, httpHeaders);
ResponseEntity mediaDTORespOnseEntity= restTemplate.postForEntity(uri, request, String.class);

​​https://work.weixin.qq.com/api/doc/90000/90135/90253​​

我有一个servlet,它能够接收二进制数据[文件].
我想使用Spring的RestTemplate()将大型二进制文件上传到servlet.但是,无法将二进制文件完全加载到内存中.
到目前为止,我的尝试导致OutOfMemory错误,表明方法一直在尝试将整个文件加载到内存中.
如何将此二进制数据流式传输到servlet?优选在Spring或Java中.
找到答案:
https://jira.springsource.org/browse/SPR-7909
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setBufferRequestBody(false);
RestTemplate rest = new RestTemplate(requestFactory);
这可以防止将整个请求加载到内存中.

微信企业号开发:上传文件错误44001,"errmsg":"empty media data

上传文件是经常出现错误"errcode":44001,"errmsg":"empty media data

对照文档一直很难发发小错误,最后才发现是因为缺少了回车换行符

1开始boundary之后需要一个回车换行

2Content-Type之后需要两个回车换行

3文件内容结束后需要一个回车换行

4结束boundary之后需要一个回车换行

///


/// 执行带文件上传的HTTP POST请求。
///

/// 请求地址
/// 请求文件参数
/// HTTP响应
public string DoPostFile(string url, FileItem fileParams)

try

string boundary = DateTime.Now.Ticks.ToString("X"); // 随机分隔线
string startboundary = "--" + boundary;
string endboundary = "--" + boundary + "--";
HttpWebRequest req = GetWebRequest(url, "POST");
req.COntentType= "multipart/form-data;boundary=" + boundary;
System.IO.Stream reqStream = req.GetRequestStream();
//开始结束的换行符不能少,否则是44001,"errmsg":"empty media data,
byte[] endBoundaryBytes = Encoding.UTF8.GetBytes("\\r\\n" + endboundary + "\\r\\n");
string name = fileParams.GetFileName();
string filename = fileParams.GetFileName();
//结束的两个换行符不能少,否则是44001,"errmsg":"empty media data,
string fileTemplate = "Content-Disposition: form-data; name=\\"0\\";filename=\\"1\\"; filelength=2\\r\\nContent-Type: 3\\r\\n\\r\\n";
FileItem fileItem = fileParams;
byte[] fileBytes = fileItem.GetContent();
StringBuilder sb = new StringBuilder();
sb.Append(startboundary);
sb.Append("\\r\\n");
sb.Append(string.Format(fileTemplate, name, filename, fileBytes.Length, fileItem.GetMimeType()));
// LogInfo.Error("sb.ToString()=" + sb.ToString());
byte[] COntent= Encoding.UTF8.GetBytes(sb.ToString());
//开始标志
reqStream.Write(Content, 0, Content.Length);
//文件内容
reqStream.Write(fileBytes, 0, fileBytes.Length);
//结束标志
reqStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
// LogInfo.Error("endBoundaryBytes=" + endboundary);
reqStream.Close();
HttpWebResponse rsp = (HttpWebResponse)req.GetResponse();
Encoding encoding = Encoding.GetEncoding(rsp.CharacterSet);
return GetResponseAsString(rsp, encoding);

catch (WebException ex)

LogInfo.Error("调用微信接口异常WebException,this._timeout" + this._timeout + ",url=" + url, ex);
ReturnResult rt = new ReturnResult();
rt.errcode = 41001;
rt.errmsg = "调用微信接口异常WebException;" + ex.Message;
return Tools.ToJsonString(rt);


restTemplate转发接收的文件,直接上传图片。
用multipart形式上传文件时,需要用到MultiValueMap类,用它装载文件对象以及multipart的表单数据。
这里涉及到一个文件,从request中拿文件往MultiValueMap放时,不能直接request.getFile()给multiValueMap,这样在restTemplate上传文件时,messageConverter转化时会报错,需要把request.getFile("file").getResource()的数据给multiValueMap。代码如下:

public UploadResponseVO resendUpload(String url,StandardMultipartHttpServletRequest request) throws IOException
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap parts = new LinkedMultiValueMap<>();
parts.add("file",request.getFile("file").getResource());
Enumeration enumeration= request.getParameterNames();
while(enumeration.hasMoreElements())
String key = enumeration.nextElement();
parts.add(key,request.getParameter(key));

HttpEntity> httpEntity = new HttpEntity<>(parts, headers);
ResponseEntity respOnseEntity= restTemplate.postForEntity(url,httpEntity,UploadResponseVO.class);
return responseEntity.getBody();

 







推荐阅读
  • 优化后的标题:深入探讨网关安全:将微服务升级为OAuth2资源服务器的最佳实践
    本文深入探讨了如何将微服务升级为OAuth2资源服务器,以订单服务为例,详细介绍了在POM文件中添加 `spring-cloud-starter-oauth2` 依赖,并配置Spring Security以实现对微服务的保护。通过这一过程,不仅增强了系统的安全性,还提高了资源访问的可控性和灵活性。文章还讨论了最佳实践,包括如何配置OAuth2客户端和资源服务器,以及如何处理常见的安全问题和错误。 ... [详细]
  • 服务器部署中的安全策略实践与优化
    服务器部署中的安全策略实践与优化 ... [详细]
  • Spring框架中枚举参数的正确使用方法与技巧
    本文详细阐述了在Spring Boot框架中正确使用枚举参数的方法与技巧,旨在帮助开发者更高效地掌握和应用枚举类型的数据传递,适合对Spring Boot感兴趣的读者深入学习。 ... [详细]
  • 深入解析CAS机制:全面替代传统锁的底层原理与应用
    本文深入探讨了CAS(Compare-and-Swap)机制,分析了其作为传统锁的替代方案在并发控制中的优势与原理。CAS通过原子操作确保数据的一致性,避免了传统锁带来的性能瓶颈和死锁问题。文章详细解析了CAS的工作机制,并结合实际应用场景,展示了其在高并发环境下的高效性和可靠性。 ... [详细]
  • C++ 异步编程中获取线程执行结果的方法与技巧及其在前端开发中的应用探讨
    本文探讨了C++异步编程中获取线程执行结果的方法与技巧,并深入分析了这些技术在前端开发中的应用。通过对比不同的异步编程模型,本文详细介绍了如何高效地处理多线程任务,确保程序的稳定性和性能。同时,文章还结合实际案例,展示了这些方法在前端异步编程中的具体实现和优化策略。 ... [详细]
  • 开发日志:201521044091 《Java编程基础》第11周学习心得与总结
    开发日志:201521044091 《Java编程基础》第11周学习心得与总结 ... [详细]
  • Squaretest:自动生成功能测试代码的高效插件
    本文将介绍一款名为Squaretest的高效插件,该工具能够自动生成功能测试代码。使用这款插件的主要原因是公司近期加强了代码质量的管控,对各项目进行了严格的单元测试评估。Squaretest不仅提高了测试代码的生成效率,还显著提升了代码的质量和可靠性。 ... [详细]
  • 在《Linux高性能服务器编程》一书中,第3.2节深入探讨了TCP报头的结构与功能。TCP报头是每个TCP数据段中不可或缺的部分,它不仅包含了源端口和目的端口的信息,还负责管理TCP连接的状态和控制。本节内容详尽地解析了TCP报头的各项字段及其作用,为读者提供了深入理解TCP协议的基础。 ... [详细]
  • Python多线程编程技巧与实战应用详解 ... [详细]
  • 本文介绍了如何利用Struts1框架构建一个简易的四则运算计算器。通过采用DispatchAction来处理不同类型的计算请求,并使用动态Form来优化开发流程,确保代码的简洁性和可维护性。同时,系统提供了用户友好的错误提示,以增强用户体验。 ... [详细]
  • 为了在Hadoop 2.7.2中实现对Snappy压缩和解压功能的原生支持,本文详细介绍了如何重新编译Hadoop源代码,并优化其Native编译过程。通过这一优化,可以显著提升数据处理的效率和性能。此外,还探讨了编译过程中可能遇到的问题及其解决方案,为用户提供了一套完整的操作指南。 ... [详细]
  • 使用Maven JAR插件将单个或多个文件及其依赖项合并为一个可引用的JAR包
    本文介绍了如何利用Maven中的maven-assembly-plugin插件将单个或多个Java文件及其依赖项打包成一个可引用的JAR文件。首先,需要创建一个新的Maven项目,并将待打包的Java文件复制到该项目中。通过配置maven-assembly-plugin,可以实现将所有文件及其依赖项合并为一个独立的JAR包,方便在其他项目中引用和使用。此外,该方法还支持自定义装配描述符,以满足不同场景下的需求。 ... [详细]
  • 本文介绍了如何利用ObjectMapper实现JSON与JavaBean之间的高效转换。ObjectMapper是Jackson库的核心组件,能够便捷地将Java对象序列化为JSON格式,并支持从JSON、XML以及文件等多种数据源反序列化为Java对象。此外,还探讨了在实际应用中如何优化转换性能,以提升系统整体效率。 ... [详细]
  • 在 Vue 应用开发中,页面状态管理和跨页面数据传递是常见需求。本文将详细介绍 Vue Router 提供的两种有效方式,帮助开发者高效地实现页面间的数据交互与状态同步,同时分享一些最佳实践和注意事项。 ... [详细]
  • 在Ubuntu上安装MySQL时解决缺少libaio.so.1错误及libaio在MySQL中的重要性分析
    在Ubuntu系统上安装MySQL时,遇到了缺少libaio.so.1的错误。本文详细介绍了如何解决这一问题,并深入探讨了libaio库在MySQL性能优化中的重要作用。对于初学者而言,理解这些依赖关系和配置步骤是成功安装和运行MySQL的关键。通过本文的指导,读者可以顺利解决相关问题,并更好地掌握MySQL在Linux环境下的部署与管理。 ... [详细]
author-avatar
扫地僧2502896033
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有